
import json
import re
import pandas as pd


def cond_parse(data, condition):
    # 返回满足条件的位置布尔值
    condition_cp = condition
    condition = condition.lower()
    if condition == 'none':
        cond = pd.isnull(data)
    elif condition == 'else':
        assert data.dtype == bool, '为 else 时， data 需给出之前结果的并集'
        cond = ~data  # 反转所有已经处理过的条件的布尔值，得到其他情况
    else:
        p = re.match(r'\((\S+),\s*(\S+)[\]\)]', condition)
        if p:  # 数值型特征
            p = p.groups()
            cond = pd.notnull(data)
            if p[0].lower() != '-inf':
                cond = cond & (data > float(p[0]))
            if p[1].lower() != '+inf':
                cond = cond & (data <= float(p[1]))
        else:  # 类别型特征
            cond = json.loads(condition_cp)
            cond = data.apply(lambda x: x in cond)
    return cond


def transform_value_to_score(binning, data, score='score', remove=[]):
    res_score = data.copy()
    for var_name in binning['var_name'].unique():
        #         print(var_name)
        if var_name not in data.columns and var_name not in remove:
            continue
        cond_ = cond_parse(data[var_name], 'None')
        index = binning[(binning['var_name'] == var_name) & (binning['split_list'] == 'None')].index[0]
        res_score.loc[cond_, var_name] = binning.loc[index, score]
        for index in binning.loc[binning['var_name'] == var_name].index:
            condition = binning.loc[index, 'split_list']
            if condition.lower() in ['none', 'else']:
                continue
            _cond = cond_parse(data[var_name], condition)
            cond_ = cond_ | _cond
            res_score.loc[_cond, var_name] = binning.loc[index, score]
        _cond = cond_parse(cond_, 'Else')
        index = binning[(binning['var_name'] == var_name) & (binning['split_list'] == 'Else')].index[0]
        res_score.loc[_cond, var_name] = binning.loc[index, score]
    return res_score



